<template>
  <component ref="FormRef" :is="renderForm(props.schema, form)"></component>
</template>

<script lang="ts" setup>
import { ref, h, PropType, computed } from "vue";
import { useI18n } from "vue-i18n";
import {
  NForm,
  NFormItem,
  NInput,
  NGrid,
  NFormItemGi,
  NSwitch,
  NSelect,
  NSlider,
  NColorPicker,
  NCheckboxGroup,
  NCheckbox,
  NSpace,
  NRadioGroup,
  NRadio,
  NTimePicker,
  NDatePicker,
  NUpload,
  NPopselect,
  NCollapse,
  NCollapseItem,
  NInputNumber,
  NDynamicInput,
  NImage,
  NButton,
} from "naive-ui";
import { IForm, IFormItem } from "./struct";
import {
  OnBeforeUpload,
  SettledFileInfo,
} from "naive-ui/es/upload/src/interface";
import { getUploadparams } from "@/api/upload";
import { v1 } from "uuid";
// const files = ref<any>([]);
const formRefs = {};
const uploadParams = ref<any>({});
const { locale, t } = useI18n();
const FormRef = ref();
const props = defineProps({
  schema: {
    type: Object as PropType<IForm>,
    required: true,
  },
});

const form = ref<any>({});
const rules = computed(() => {
  const ruleForm: any = {};
  props.schema.columns.forEach((item) => {
    if (item.required) {
      ruleForm[item.prop] = {
        required: true,
        message:
          locale.value == "zh"
            ? item.name + t("required")
            : item.enName || item.name + t("required"),
        trigger: ["blur", "change"],
      };
      if (item.props && item.props.multiple) {
        ruleForm[item.prop].type = "array";
      } else if (item.props && item.props.options) {
        // ruleForm[item.prop].type = "array";
        if (item.props.options.length > 0) {
          // if(typeof item.props.options[0].value == "")
          ruleForm[item.prop].type = typeof item.props.options[0].value;
        }
      }
    }
  });
  console.log(ruleForm);
  return ruleForm;
});
const genRule = (columns: Array<IFormItem>) => {
  const ruleForm: any = {};
  columns.forEach((item) => {
    if (item.required) {
      ruleForm[item.prop] = {
        required: true,
        message:
          locale.value == "zh"
            ? item.name + t("required")
            : item.enName || item.name + t("required"),
        trigger: ["blur", "change"],
      };
      if ((item.props && item.props.multiple) || item.type == "kv") {
        ruleForm[item.prop].type = "array";
      } else if (item.props && item.props.options) {
        // ruleForm[item.prop].type = "array";
        if (item.props.options.length > 0) {
          // if(typeof item.props.options[0].value == "")
          ruleForm[item.prop].type = typeof item.props.options[0].value;
        }
      }
    }
  });
  console.log(ruleForm);
  return ruleForm;
};
const getExtension = (fileName: string) => {
  const lastDotIndex = fileName.lastIndexOf(".");

  // 检查是否有后缀名
  return lastDotIndex >= 0 ? fileName.substring(lastDotIndex + 1) : "";
};
const renderFormItem = (item: IFormItem, subForm: any) => {
  //   return h()
  // const item = h()
  //   const formItem = h(NFormItem, { prop: item.prop });

  if (item.default != null && subForm[item.prop] == null) {
    subForm[item.prop] = item.default;
  }
  let slotItem;
  if (!item.props) {
    item.props = {};
  }
  const attrs = {
    value: subForm[item.prop],
    "onUpdate:value": (val: string) => {
      subForm[item.prop] = val;
    },
    ...item.props,
  };
  switch (item.type) {
    case "text":
      slotItem = h(NInput, attrs);
      break;
    case "number":
      slotItem = h(NInputNumber, attrs);
      break;
    case "switch":
      slotItem = h(NSwitch, attrs);
      break;
    case "select":
      slotItem = h(NSelect, attrs);
      break;
    case "slider":
      slotItem = h(NSlider, attrs);
      break;
    case "color":
      slotItem = h(NColorPicker, attrs);
      break;
    case "checkbox":
      slotItem = h(NCheckboxGroup, attrs, {
        default: () =>
          h(
            NSpace,
            {},
            {
              default: () =>
                item.props?.options?.map((subItem) =>
                  h(NCheckbox, {
                    label: subItem.label as string,
                    value: subItem.value as string,
                  })
                ),
            }
          ),
      });
      break;
    case "radio":
      slotItem = h(NRadioGroup, attrs, {
        default: () =>
          h(
            NSpace,
            {},
            {
              default: () =>
                item.props?.options?.map((subItem) =>
                  h(NRadio, {
                    label:
                      locale.value == "zh"
                        ? (subItem.label as string)
                        : (subItem.enLabel as string) ||
                          (subItem.label as string),
                    value: subItem.value as string,
                  })
                ),
            }
          ),
      });
      break;
    case "time":
      slotItem = h(NTimePicker, attrs);
      break;
    case "date":
      slotItem = h(NDatePicker, {
        formattedValue: form.value[item.prop],
        "onUpdate:formattedValue": (val: string) => {
          console.log(val);
          form.value[item.prop] = val;
        },
        ...item.props,
      });
      break;
    case "image-upload":
      if (subForm[item.prop]) {
        slotItem = h(
          NSpace,
          { align: "center" },
          {
            default: () => [
              h(NImage, {
                src: subForm[item.prop],
                objectFit: "contain",
                style: { height: "80px" },
              }),
              h(
                NButton,
                {
                  type: "error",
                  size: "small",
                  secondary: true,
                  onClick() {
                    subForm[item.prop] = null;
                  },
                },
                { default: () => "删除" }
              ),
            ],
          }
        );
      } else {
        slotItem = h(NUpload, {
          listType: "image-card",
          action: "https://xunjinasd.oss-cn-hangzhou.aliyuncs.com",
          data: uploadParams.value,
          max: 1,
          onRemove() {
            subForm[item.prop] = null;
          },
          onUpdateFileList(val) {
            // console.log(val);
            // subForm[item.prop] = val;
            // files.value = val;
            // subForm[item.prop] =
            //   uploadParams.value["host"] + "/" + uploadParams.value["key"];
            if (val.length > 0 && val[0].status == "finished") {
              subForm[item.prop] =
                uploadParams.value["host"] + "/" + uploadParams.value["key"];
            }
          },
          onBeforeUpload: async (options: {
            file: SettledFileInfo;
            fileList: SettledFileInfo[];
          }) => {
            // console.log(options);
            // getUploadparams;
            const paramsData = await getUploadparams();
            console.log(paramsData, options.file);

            uploadParams.value = {
              ...paramsData["data"],
              key: `qa/${v1()}.${getExtension(options.file.name)}`,
            };
            return true;
          },
          defaultFileList: subForm[item.prop]
            ? [
                {
                  id: subForm[item.prop],
                  name: subForm[item.prop],
                  status: "finished",
                  url: subForm[item.prop],
                },
              ]
            : [],
          // fileList: [
          //   {
          //     id: subForm[item.prop],
          //     name: subForm[item.prop],
          //     status: "finished",
          //     url: subForm[item.prop],
          //   },
          // ],
          ...item.props,
        });
      }

      break;
    case "collapse":
      slotItem = h(NCollapse, attrs, {
        default: () =>
          item.columns.map((subItem) => {
            if (!subForm[item.prop]) {
              subForm[item.prop] = {};
            }
            return h(NCollapseItem, subItem.props, {
              default: () =>
                subItem.columns.map((subItem2) => {
                  return renderFormItem(subItem2, subForm[item.prop]);
                }),
            });
          }),
      });
      break;
    case "group":
      if (!subForm[item.prop]) {
        subForm[item.prop] = {};
      }
      slotItem = renderForm(
        { title: item.name, columns: item.columns },
        subForm[item.prop]
      );
      break;
    case "kv":
      // if (!subForm[item.prop]) {
      //   subForm[item.prop] = [];
      // }
      slotItem = h(NDynamicInput, attrs);
      break;
    default:
      slotItem = "--";
  }
  return handleCheckVisible(subForm, item)
    ? h(
        NFormItemGi,
        {
          label: locale.value == "zh" ? item.name : item.enName || item.name,
          path: item.prop,
          span: item.span || 24,
        },
        { default: () => slotItem }
      )
    : h("div");
};
const renderForm = (schema: IForm, subForm: any) => {
  const formRef = ref();
  formRefs[schema.title] = formRef;
  return h(
    NForm,
    {
      labelPlacement: (schema.labelPlacement as any) || "top",
      size: schema.size || "medium",
      labelWidth: schema.labelWidth,
      rules: genRule(schema.columns),
      model: subForm,
      class: ["form"],
      style: {
        marginLeft: "12px",
      },
      ref: formRef,
    },
    {
      default: () =>
        h(
          NGrid,
          { cols: schema.cols || 24, xGap: schema.gap || 12 },
          {
            default: () =>
              schema.columns.map((item) => renderFormItem(item, subForm)),
          }
        ),
    }
  );
};

const handleCheckVisible = (subForm: any, item: IFormItem) => {
  if (item.visible) {
    // if(item.visible)
    for (let i = 0; i < item.visible.length; i++) {
      if (typeof item.visible[i] == "string") {
        if (subForm[item.visible[i] as string] == null) {
          return false;
        }
      } else {
        const rule = item.visible[i] as Array<string>;
        const key = rule[0];
        const express = rule[1];
        const value = rule[2];
        if (express == "=") {
          if (subForm[key] != value) {
            return false;
          }
        } else if (express == ">") {
          if (subForm[key] < value) {
            return false;
          }
        } else if (express == "<") {
          if (subForm[key] > value) {
            return false;
          }
        } else if (express == "!=") {
          if (subForm[key] == value) {
            return false;
          }
        }
      }
    }
  }
  return true;
};
const subimt = () => {
  const promiseList = [];
  for (let key in formRefs) {
    promiseList.push(
      new Promise((resolve, reject) => {
        if (formRefs[key].value) {
          formRefs[key].value.validate((errors) => {
            if (errors) {
              reject(errors);
            } else {
              resolve(form.value);
            }
          });
        } else {
          resolve({});
        }
      })
    );
  }
  return new Promise((resolve, reject) => {
    Promise.all(promiseList)
      .then((res) => {
        resolve(form.value);
      })
      .catch((e) => {
        console.log(e);
        reject(e);
      });
  });
  // return new Promise.all();
  // return form.value;
};
const setForm = (data: any) => {
  form.value = data;
};
defineExpose({ subimt, setForm });
</script>

<style lang="scss" scoped>
.form {
  position: relative;
}
.form:after {
  content: "";
  position: absolute;
  height: 100%;
  width: 0px;
  // background-color: rgba(255, 255, 2555, 0.05);
  border-left: 1px dashed rgba(255, 255, 2555, 0.05);
  left: -12px;
  top: 0px;
  border-radius: 2px;
}
</style>
